package com.atguigu.stack;

public class Calculator {
    public static void main(String[] args) {
        //根据思路，完成表达式的运算
        String str="300+20*6-2";
        //创建两个栈，数栈，符号栈
        ArrayStack2 numstack=new ArrayStack2(10);
        ArrayStack2 operstack=new ArrayStack2(10);
        //定义相关的变量
        int index=0;//用于扫描
        int num1=0;
        int num2=0;
        int oper=0;
        int res=0;
        char ch=' ';
        String keepNum="";
        char[] chs=str.toCharArray();
        //开始扫描
        for (int i = 0; i < chs.length; i++) {
            //判断ch是什么,进行相应的运算
            if(operstack.isOper(chs[i])){//chs[i]是运算符
                //判断当前符号栈是否为空
                if(!operstack.isEmpty()){
                    //不为空，如果有操作符，那就进行比较，
                    /*
                    * 如果当前的符号优先级小于或者等于栈中的操作符，就需要从numstack中pop出两个数，
                    * 在从operStack中pop出一个符号进行运算
                    * 将得到的结果，入栈
                    * 将当前的操作符入栈
                    *
                    * */
                    if(operstack.prioroty(chs[i])<=operstack.prioroty(operstack.peak())){
                        num1=numstack.pop();
                        num2=numstack.pop();
                        oper=operstack.pop();
                        res=numstack.cal(num1,num2,oper);
                        numstack.push(res);
                        operstack.push(chs[i]);
                    }else{
                        operstack.push(chs[i]);
                    }
                }else{
                    //为空直接入符号栈
                    operstack.push(chs[i]);
                }

            }else{
                //如果是数，直接入数栈
//                numstack.push(chs[i]-48);
                //处理多位数时，不能发现一个数就立即入栈，因为可能时多位数
                //如果是数，不能马上入栈。
                //如何使符号，直接入栈
                //定义一个字符串
                keepNum+=chs[i];
                //如果ch[i]是最后一位，则直接入栈
                if(i==str.length()-1){
                    numstack.push(Integer.parseInt(keepNum));
                }else{
                    if(operstack.isOper(chs[(i+1)])){
                        //如果后一位是运算符，则入栈
                        numstack.push(Integer.parseInt(keepNum));
                        //清空keepNum
                        keepNum="";
                    }
                }

            }
        }
        //当表达式扫描结束以后，就顺序的从数栈和符号栈pop出相应的数和符号进行运算
        while (true){
            //如果符号栈为空，则计算到最后结果，数栈中只有一个数字
            if(operstack.isEmpty()){
                break;
            }
            num1=numstack.pop();
            num2=numstack.pop();
            oper=operstack.pop();
            res=numstack.cal(num1,num2,oper);
            numstack.push(res);

        }
        //将数栈的结果导出
        System.out.println("结果为"+numstack.pop());
    }
    
    
}

class ArrayStack2{
    private int maxSize;//栈的大小
    private int[] stack;//数组模拟栈
    private int top=-1;//表示栈顶，初始化为1
    //构造器
    public ArrayStack2(int size){
        this.maxSize=size;
        stack=new int[size];
    }
    //栈满
    public boolean isFull(){
        return top==maxSize-1;
    }
    //栈空
    public boolean isEmpty(){
        return top==-1;
    }
    //入栈
    public void push(int n){
        if(isFull()){
            System.out.println("栈满了，无法继续添加了");
            return;
        }
        stack[++top]=n;
    }
    //出栈
    public int pop(){
        if(isEmpty()){
            throw new RuntimeException("栈空，没有数据可以取出");
        }
        return stack[top--];
    }
    //显式栈
    public void list(){
        if(isEmpty()){
            System.out.println("栈空，没有数据可以取出");
        }
        while (top!=-1){
            System.out.printf("top%d 为%d ",top, stack[top--]);
        }
    }
    //增加一个查看栈顶元素的方法
    public int peak(){
        return stack[top];
    }
    //返回运算符的优先级，优先级使用数字表示，数字越大，优先级越高
    public int prioroty(int oper){
        if(oper=='*'||oper=='/'){
            return 1;
        }else if(oper=='+'||oper=='-'){
            return 0;
        }else {
            return -1;
        }
    }
    //判断是不是运算符
    public boolean isOper(char val){
        return val=='+'||val=='-'||val=='*'||val=='/';
    }
    public int cal(int num1, int num2,int oper){
        int res=0;
        switch (oper){
            case '+':
                res=num1+num2;
                break;
            case '-':
                res=num2-num1;
                break;
            case '*':
                res=num1*num2;
                break;
            case '/':
                res=num2/num1;
                break;
            default:
                break;

        }
        return res;
    }

}